package cn.ronghuanet.auth.service.impl;

import cn.ronghuanet.auth.dto.AccountLoginDTO;
import cn.ronghuanet.auth.dto.LoginDTO;
import cn.ronghuanet.auth.mapper.LoginMapper;
import cn.ronghuanet.auth.service.ILoginService;
import cn.ronghuanet.base.constants.WxConstants;
import cn.ronghuanet.base.exception.ResponseCode;
import cn.ronghuanet.base.exception.RonghuaAssert;
import cn.ronghuanet.base.util.BaseLoginMap;
import cn.ronghuanet.base.util.HttpUtil;
import cn.ronghuanet.base.util.MD5Utils;
import cn.ronghuanet.org.domain.Employee;
import cn.ronghuanet.user.domain.Logininfo;
import cn.ronghuanet.user.domain.Wxuser;
import cn.ronghuanet.user.mapper.LogininfoMapper;
import cn.ronghuanet.user.mapper.WxuserMapper;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private LoginMapper mapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WxuserMapper wxuserMapper;

    @Override
    public Map<String, Object> login(LoginDTO loginDTO) {
        // 验证账号或密码是否为null
        if(Objects.isNull(loginDTO)
                || Objects.isNull(loginDTO.getUsername())
                || Objects.isNull(loginDTO.getPassword())){
            throw new RuntimeException("账号或密码未输入!");
        }
        // 调用mapper查询账号是否存在
        Employee user = mapper.selectByName(loginDTO);
        if (Objects.isNull(user)) {
            throw new RuntimeException("账号或密码不正确!");
        }
        // 验证密码是否正确
        if (!user.getPassword().equals(loginDTO.getPassword())){
            throw new RuntimeException("账号或密码不正确!");
        }
        // 为了安全 将密码置为空
        user.setPassword("");
        // 随机数/token/uuid
        String token = UUID.randomUUID().toString();
        // 将登陆用户的数据放入全局的map中去 以后 会使用redis进行替换
        BaseLoginMap.loginMap.put(token,user);
        HashMap<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("loginUser",user);
        // 返回
        return map;
    }

    @Override
    public Map<String,Object> accountLogin(AccountLoginDTO dto) {
        // 1 参数非空校验  JSR303
        // 2 通过账号&type去t_logininfo中查询登录信息
        Logininfo logininfo = logininfoMapper.loadByAccountAndType(dto.getAccount(),dto.getType());

        // 3 如果登录信息不存在,返回错误信息: 账号或密码错误,请重新输入!
        RonghuaAssert.isNotNull(logininfo, ResponseCode.RESPONSE_CODE_40024);

        // 4 如果登录信息存在,比对密码,要经过MD5加密加盐之后判断,如果错误,返回错误信息
        String password = MD5Utils.encrypByMd5("ronghua"+dto.getPassword()+"1234"+logininfo.getSalt());
        RonghuaAssert.isEq(password,logininfo.getPassword(),ResponseCode.RESPONSE_CODE_40024);

        Map<String, Object> map = loginSuccess(logininfo);
        return map;
    }

    /**
     * 登录成功以后要做的事情
     * @param logininfo
     * @return
     */
    public Map<String, Object> loginSuccess(Logininfo logininfo) {
        // 5 如果密码正确,生成uuid随机字符串作为token
        String token = UUID.randomUUID().toString();

        // 6 将token作为redis的key,登录信息作为value,存入redis,设置30分钟过期时间
        redisTemplate.opsForValue().set(token, logininfo,30, TimeUnit.MINUTES);

        // 7 返回token和登录信息给前端
        Map<String,Object> map = new HashMap<>();
        map.put("token",token);
        // 比如盐值或者密码这些敏感字段,是不能直接返回给前端的
        logininfo.setSalt("");
        logininfo.setPassword("");
        map.put("loginUser", logininfo);
        return map;
    }

    @Override
    public Map<String, Object> wechatLogin(String code) {
        // 1 通过code&appid&appsecrect调用微信接口,获取accessToken,openid
        String ackUrl = WxConstants.GET_ACK_URL.replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code);
        String ackStr = HttpUtil.httpGet(ackUrl);   // {access_token:"",openid:""}
        // 将json字符串转为json对象
        JSONObject ackObj = JSONObject.parseObject(ackStr);
        String accessToken = ackObj.getString("access_token");
        String openid = ackObj.getString("openid");

        // 2 通过openid获取微信用户信息
        Wxuser wxuser = wxuserMapper.loadByOpenid(openid);

        // 3 如果微信用户存在,就直接做免密登录
        // 所谓免密登录,它的含义就是说 需要在后端将token和登录信息存入redis,并将它们返回给前端
        if(Objects.nonNull(wxuser)){
            // 3.1 获取到当前微信用户所对应的logininfo信息
            Logininfo logininfo = logininfoMapper.loadByUserId(wxuser.getUserId());
            Map<String, Object> map = loginSuccess(logininfo);
            return map;
        }
        // 4 如果不存在,携带accessToken,openid跳转回绑定页面
        Map<String,Object> map = new HashMap<>();
        map.put("accessToken",accessToken);
        map.put("openid",openid);
        map.put("message","noBind");
        return map;
    }
}
